package com.blog.service.service;

import com.blog.check.check.CheckResult;
import com.blog.check.check.UserCheck;
import com.blog.check.result.Result;
import com.blog.check.resultenum.ProfileChkRsEnum;
import com.blog.check.resultenum.UserChkRsEnum;
import com.blog.dao.domain.BlogDO;
import com.blog.dao.domain.ProfileDO;
import com.blog.dao.domain.UserDO;
import com.blog.dao.query.UserQuery;
import com.blog.exception.ServiceException;
import com.blog.form.ProfileForm;
import com.blog.form.UserForm;
import com.blog.service.dto.BlogDTO;
import com.blog.service.dto.UserDTO;
import com.blog.until.BeanCopierUtil;
import com.blog.until.PrimaryKeyUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.SneakyThrows;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Base64Utils;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * 用户服务
 *
 * @author 泡面ing
 * @date 2021/11/17
 */
@Service
public class UserService extends BaseService{

    private  ProfileService profileService;
    private UserCheck userCheck;

    @Autowired
    public void setProfileService(ProfileService profileService){
        this.profileService = profileService;
    }
    @Autowired
    public void setUserCheck(UserCheck userCheck){
        this.userCheck = userCheck;
    }

    @Transactional(rollbackFor = Exception.class)
    public Result list(int pageNum, int pageSize, UserQuery userQuery){

        try {
            CheckResult checkResult = userCheck.checkList(userQuery);
            if (checkResult.getCode() != UserChkRsEnum.SUCCESS.getCode()){
                logger.error(logInfo(checkResult));
                return Result.failure(checkResult);
            }
            List<UserDTO> userDTOList = new ArrayList<>();

            List<UserDO> userDOList = userDAO.list(userQuery);

            if (userDOList.size() == 0){
                return Result.success(userDTOList);
            }
            for (UserDO userDO : userDOList){
                UserDTO userDTO = getShowDTO(userDO);
                userDTOList.add(userDTO);
            }
            PageHelper.startPage(pageNum,pageSize);
            PageInfo<UserDTO> pageInfo = new PageInfo<>(userDTOList);
            return Result.success(pageInfo);
        }catch (Exception e){
            throw new ServiceException(e);
        }
    }

    private UserDTO getShowDTO(UserDO userDO) throws IOException {
        UserDTO userDTO = new UserDTO();
        userDTO.setUserName(userDO.getUserName());
        userDTO.setPassword(userDO.getPassword());
        ProfileDO profileDO = userDO.getProfile();
        File file = new File(profileDO.getImageName());
        if (file.exists()){
            byte[] bytes = FileUtils.readFileToByteArray(file);
            String icon = getImageBase64Prefix(file) + "," + Base64Utils.encodeToString(bytes);
            profileDO.setImageName(icon);
        }
        userDTO.setProfile(profileDO);
        userDTO.setDisable(userDO.getDisable());
        userDTO.setDisableMessage(userDO.getDisableMessage());
        userDTO.setJurisdiction(userDO.getJurisdiction());
        userDTO.setPhoneNumber(userDO.getPhoneNumber());
        userDTO.setEmail(userDO.getEmail());
        userDTO.setGmtCreate(userDO.getGmtCreate());
        return userDTO;
    }

    @Transactional(rollbackFor = Exception.class)
    public Result get(String id, HttpServletRequest request){
        UserDTO userDTO = null;
        UserDO userDO = userDAO.get(id);
        try {
            userDTO = getShowDTO(userDO);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Result.success(userDTO);
    }

    @Transactional(rollbackFor = Exception.class)
    public Result save(UserForm userForm){
        try{
            CheckResult checkResult = userCheck.checkSave(userForm);
            if (checkResult.getCode() != ProfileChkRsEnum.SUCCESS.getCode()){
                logger.error(logInfo(checkResult));
                return Result.failure(checkResult);
            }

            UserDO userDO = buildSaveUser(userForm);
            userDAO.save(userDO);


            ProfileForm profileForm = userForm.getProfile();

            profileForm.setId(userDO.getProfileId());
            profileForm.setNickName(userDO.getUserName());

            profileService.save(profileForm);
            return Result.success();
        }catch (Exception e){
            throw new ServiceException(e);
        }

    }
    @SneakyThrows
    private UserDO buildSaveUser(UserForm userForm) {
        UserDO userDO = BeanCopierUtil.create(userForm,UserDO.class);
        userDO.setUserName(userForm.getUserName());
        String password = DigestUtils.md5DigestAsHex(userForm.getPassword().getBytes(StandardCharsets.UTF_8));
        userDO.setPassword(password);
        userDO.setDisable(false);
        userDO.setDisableMessage(null);
        userDO.setPhoneNumber(userForm.getPhoneNumber());
        userDO.setEmail(userForm.getEmail());
        userDO.setGmtCreate(getTime());
        userDO.setProfileId(PrimaryKeyUtil.get());
        userDO.setJurId("2");
        ProfileDO profileDO = new ProfileDO();
        userDO.setProfile(profileDO);
        return userDO;
    }

    @Transactional(rollbackFor = Exception.class)
    public Result update(UserForm userForm){
        CheckResult checkResult = userCheck.checkUpdate(userForm);
        if (checkResult.getCode() != UserChkRsEnum.SUCCESS.getCode()){
            logger.error(logInfo(checkResult));
            return Result.failure(checkResult);
        }

        try{
            String userName = getUsername();
            UserDO userDO = buildUpdateUser(userName,userForm);
            userDAO.update(userDO);

            return Result.success();
        }catch(Exception e){
            throw new ServiceException(e);
        }
    }

    private UserDO buildUpdateUser(String userName, UserForm userForm) throws
            InstantiationException ,IllegalAccessException{

        UserDO userDO = userDAO.get(userName);
        UserDO newUserDO = BeanCopierUtil.create(userDO,UserDO.class);
        if (StringUtils.isNotBlank(userForm.getPhoneNumber())){
            newUserDO.setPhoneNumber(userForm.getPhoneNumber());
        }
        if (StringUtils.isNotBlank(userForm.getEmail())){
            newUserDO.setEmail(userForm.getEmail());
        }
        return newUserDO;
    }
    @Transactional(rollbackFor = Exception.class)
    public Result changeDisable(String username, boolean disable,String disableMessage) {

        CheckResult checkResult = userCheck.checkDisable(username);
        if (checkResult.getCode() != UserChkRsEnum.SUCCESS.getCode()){
            logger.error(logInfo(checkResult));
            return Result.failure(checkResult);
        }

        try{
            UserDO userDO = buildUpdateDisable(username,disable,disableMessage);
            userDAO.updateDisable(userDO);

            return Result.success();
        }catch(Exception e){
        throw new ServiceException(e);
    }

    }

    private UserDO buildUpdateDisable(String username, boolean disable, String disableMessage)throws
            InstantiationException ,IllegalAccessException{
        UserDO userDO = userDAO.get(username);
        UserDO newUserDO = BeanCopierUtil.create(userDO,UserDO.class);
        newUserDO.setDisable(disable);
        newUserDO.setDisableMessage(disableMessage+getUsername());

        return newUserDO;

    }
    @Transactional(rollbackFor = Exception.class)
    public Result changePassword(UserForm userForm){
        try{
            String username = getUsername();
            UserDO userDO = buildUpdatePassword(userForm,username);
            userDAO.updatePwd(userDO);
            return Result.success();
        }catch (Exception e){
            throw new ServiceException(e);
        }
    }

    private UserDO buildUpdatePassword(UserForm userForm,String username) throws InstantiationException, IllegalAccessException {
        UserDO userDO = userDAO.get(username);
        UserDO newUserDO = BeanCopierUtil.create(userDO,UserDO.class);
        String password = DigestUtils.md5DigestAsHex(userForm.getPassword().getBytes(StandardCharsets.UTF_8));
        newUserDO.setPassword(password);
        return newUserDO;

    }

}
